//
// Created by Administrator on 2021/10/21.
//

#ifndef MRENDER_SHADER_H
#define MRENDER_SHADER_H


#include "../../core/String.h"
#include "../../core/FileUtil.h"
#include "../../constant/Properties.h"
#include "../../core/Log.h"
#include "../../core/MAssert.h"
#include "../../math/Color.h"
#include "../../core/Object.h"
#include "../../math/Matrix4x4.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>

/**
 * attribute 属性
 */
class ShaderAttribute{
public:
    ShaderAttribute(const String attribName, const GLuint dataType = GL_FLOAT,  const int numComponent = 3, const bool normalize = false) {
        this->attribName = attribName;
        this->dataType = dataType;
        this->numComponent = numComponent;
        this->normalize = normalize;
    }
    //shader中该字段名称
    String attribName;
    //参数个数，如 vec3-> 3, vec4->4
    int numComponent;
    //类型
    GLuint dataType;
    //是否标准化
    bool normalize;
};

/**
 * attribute 操作对象，创建VBO使用
 * //1、 VBO unsign int对象
 * //2、 attribute的index
 * //3、 attribute的numPoints
 * //5、 attribute值是否normalize
 */
class ShaderAttribBuffer{
public:
    /**
     * AttributeBuffer对象
     * @param attribName 属性名称
     * @param location Shader中的location值
     * @param numComponent 组成的数据个数
     * @param dataType 数据类型 GL_FLOAT...
     * @param normalize 是否标准化
     * @param data 数据
     */
    ShaderAttribBuffer(String attribName, int location, int numComponent, GLuint dataType, bool normalize, std::vector<float> data) {
        this->attribName = attribName;
        this->location = location;
        this->numComponent = numComponent;
        this->dataType = dataType;
        this->normalize = normalize;
        this->data = data;
    }
    //shader中该字段名称
    String attribName;
    //shader中该字段的下标
    int location;
    //参数个数，如 vec3-> 3, vec4->4
    int numComponent;
    //类型
    GLuint dataType;
    bool normalize;
    //ABO
    GLuint VAO = 0;
    //VBO
    GLuint VBO = 0;
    //EBO
    GLuint EBO = 0;
    //原始数据
    std::vector<float> data;
};

class Shader : public Object{
private:
    /**
     * 名称
     */
    String name;
    /**
     * 编译后shader程序
     */
    GLuint program;
private:
    /**
     * 编译Shder源码
     * @param vertexShaderSource 顶点着色器源码
     * @param fragmentShaderSource 片元着色器源码
     */
    GLuint compileProgram(String vertexShaderSource, String fragmentShaderSource);

public:
    /**
     * 获得shder对象，使用默认shder
     */
    Shader();
    /**
     * 获得shader对象并编译
     * @param vsFilePath vs文件路径
     * @param fsFilePath fs文件路径
     */
    Shader(String name, String vsFilePath, String fsFilePath);

    /**
     * 返回名称
     * @return 名称
     */
    const String &getName() const;

    /**
     * 返回当前shader的program
     * @return
     */
    GLuint getProgram() const;

    /**
     * 检查是否可用
     * @param shader
     * @return
     */
    bool check();

    /**
      * 设置单个float值
      * @param uniformVar 变量
      * @param v 值
      */
    void setUniform(const char* uniformVar, const float v) const;

    /**
      * 设置单个int值
      * @param uniformVar 变量
      * @param v 值
      */
    void setUniform(const char* uniformVar, const int v) const;

    /**
     * 设置颜色值
     * @param uniformVar 变量
     * @param m 值
     */
    void setUniform(const char* uniformVar, const Color& c) const;

    /**
     * 设置矩阵值
     * @param uniformVar 变量
     * @param m 值
     */
    void setUniform(const char* uniformVar, const Matrix4x4& m) const;
};


#endif //MRENDER_SHADER_H
